# -*- coding: utf-8 -*-
"""
Created on Mon Mar 21 16:18:19 2022
计算碲镉汞基本参数的例程
@author: lixy
"""
import Device.PhysUnit as Unit
from math import pow, expm1, exp, sqrt
from scipy.integrate import quad

class HgCdTe():
    '''
    计算碲镉汞材料的基本参数,
    初始化时可以输入组分和温度两个参数
    '''
    def __init__(self, composition=0.29, Temperature=300*Unit.K, ColdShield=True): 
        super(HgCdTe, self).__init__() #初始化材料的性质为基类的参数，实际为硅材料的
        ## 碲镉汞材料的参数，按照x=0.29计算. 300K cuttoff is 4.24um
        #
        assert (composition >= 0.0 and composition <= 1.0 ) 
        #决定碲镉汞性质的基本参数组分和温度       
        x = composition
        T = Temperature        
        self.composition = composition
        self.Temperature = Temperature 
        #碲镉汞的密度
        self.Density = (8.076-2.23*x) * Unit.g * pow(Unit.cm,-3)
        #介电常数
        self.eps_LowFreq = (20.8 - 15.6*x + 5.7*x*x)*Unit.eps0
        self.eps_HighFreq = (15.2 - 15.6*x + 8.2*x*x)*Unit.eps0
        self.eps = self.eps_LowFreq
        #禁带宽度
        #褚君浩的CXT公式
        #Eg = (-0.295 + 1.87*x - 0.28*x*x + (6-14*x+3*x*x)*1e-4*(T/Unit.K)+0.35*x**4)*Unit.eV
        #杨建荣书介绍的Laurenti公式（据说是短波修正的）
        Eg = -0.303*(1-x)+1.606*x-0.132*x*(1-x)+(6.3*(1-x)-3.25*x-5.92*x*(1-x))*(1e-4)*pow(T/(Unit.K),2)/(11*(1-x)+18.7*x+T/Unit.K)
        self.Eg = Eg
        self.affinity = 4.28*Unit.eV - 0.813*(Eg - 0.0083*Unit.eV) #4.28 is for CdTe 亲和能 X (chi)
        KbT = Unit.kb*T
        KbTeV = Unit.kb*T/Unit.eV
        self.ni = (1+3.25*KbT/Eg)*9.56e14*pow(Eg*T/Unit.K, 1.5)/(1+1.9*pow(Eg,0.75)*exp(Eg/(2*KbT)))*pow(Unit.cm, -3.0)
        #self.ni = 4.694e15*pow(Unit.cm, -3.0) #x=0.29,300K
        #self.mun0 = 6022*Unit.cm*Unit.cm/Unit.V/Unit.s
        #self.mup0 = 100*Unit.cm*Unit.cm/Unit.V/Unit.s #排脑袋的。电子/空穴比例约为60
        
        #杨建荣书籍上的公式
        ZT=Temperature/Unit.K
        if (ZT <= 50) : ZT=1.18e5/(2600-pow(abs(ZT-35),2.07))
        self.mun = 9e8*pow((0.2/x),7.5)/pow(ZT,(2.0*pow((0.2/x),0.6)))*Unit.cm*Unit.cm/Unit.V/Unit.s
        self.mup = 1/50*self.mun #排脑袋的。电子/空穴比例约为50
        #这里的迁移率应该是最理想的本征半导体的迁移率，即理想迁移率。
        #实际情况可能还需要考虑电离杂质散射和电子电子相互散射等问题
        #self.tau = 1e-8*Unit.s #按少子寿命预估
        #碲镉汞的载流子有效质量
        self.me0 = 0.05966 * Eg *(Eg+1)/(Eg+0.667)*Unit.me
        self.mh0 = 0.55 * Unit.me
        #计算辐射复合
        self.Br = 5.8e-13*sqrt(self.eps_HighFreq/Unit.eps0)*pow(Unit.me/(self.me0+self.mh0),1.5)*(1+
             Unit.me/self.me0 + Unit.me/self.mh0)*pow(300*Unit.K/T,1.5)*(Eg*Eg+
             3*KbTeV*Eg+3.75*pow(KbTeV,2))/Unit.s
        #辐射复合的寿命就等于Br*(n*p-ni*ni)~=Br*(n+p)的倒数
        #     
        #计算俄歇复合
        F1F2 = 0.2
        _rhoA1 = (Unit.me/self.me0)*pow((1+self.me0/self.mh0),0.5)*(1+2*self.me0/self.mh0)
        rhoA1  = _rhoA1 * pow(Eg/KbT,1.5)*exp((1+2*self.me0/self.mh0)/(1+self.me0/self.mh0)*(Eg/KbT)) 
        tauA1i = rhoA1*(3.8e-18*Unit.s)*pow((self.eps_HighFreq/Unit.eps0),2)*pow(F1F2,-2)
        beta   = 1.667  #拍脑袋选择的一个数,其理论值为1-3之间
        tauA7i = 2*beta*(1-5/4*Eg/KbT)/(1-3/2*Eg/KbT)*tauA1i
        self.tauA1i = tauA1i
        self.tauA7i = tauA7i        
        #俄歇复合的寿命等于 {[2*tauA1i*(ni/(n+p))*(ni/n)]**-1 +[2*tauA7i*(ni/(n+p))*(ni/p)]**-1}**-1
        #         
        #SRH复合
        self.taun0 = 1.249e-8*Unit.s #估计值1
        self.taup0 = 5.427e-8*Unit.s #估计值2 空穴有效质量大一些，估计大点，其实也是拍脑袋的
        self.NsrhN = 5e17*pow(Unit.cm,-3)#掺杂总浓度大于此数值后开始影响对应的Taun0 计算公式在DDEqns中
        self.NsrhP = 5e17*pow(Unit.cm,-3)#掺杂总浓度大于此数值后开始影响对应的Taup0 计算公式在DDEqns中
        
        #SRH复合的寿命等于 [taun0*(p+ni*exp(-Etrap/KT)+taup0*(n+ni*exp(Etrap/KT)]/(p*n-ni*ni) 其中Etrap是复合中心能级离开费米能级的大小，估计0为最有效的
        
def Mblackbody(wavelength=10*Unit.um, temperature=300*Unit.K):
    '''
    黑体辐射的普朗克公式。 结果含单位缩放是：(Unit.W/(Unit.m)**3)
    '''
    wl = wavelength
    T = temperature
    Mbb = 2*3.1415926536*Unit.h*((3e8*Unit.m/Unit.s)**2)/(wl**5)/expm1(Unit.h*(3e8*Unit.m/Unit.s)/(wl*Unit.kb*T))
    #Mbb(10u,300K)= 3.1116e7 *(Unit.W/(Unit.m)**3)
    return Mbb


def BackGroundRadiation(mct): 
    '''
    利用积分对从可见光波段到碲镉汞截止波长范围内的室温目标黑体辐射积分
    输入碲镉汞的类实例
    返回值其中包含单位，是(Unit.kg/(Unit.s)**3))
    '''
    if not isinstance(mct, HgCdTe):
        raise ValueError("错误: 输入参数应该是 Class HgCdTe。需要计算其截止波长作为积分上限")
    else:
        cutoffwavelength = 1.24 / mct.Eg * Unit.um  #计算真实的
        r,_=quad(Mblackbody,0.5*Unit.um,cutoffwavelength) #求积分，被积分函数的默认值为温度300K
        return r 

if __name__ == '__main__' :
    MCT = HgCdTe(0.29, 300*Unit.K)
    print('x=', MCT.composition)
    print('epsilon=', MCT.eps/Unit.eps0)    
    print('Eg=', MCT.Eg/(Unit.eV), 'eV')
    #print('EgC=', MCT.EgC/(Unit.eV), 'eV')
    print('ni=', MCT.ni/(pow(Unit.cm, -3.0)),'cm**-3')
    #print('mun0=', MCT.mun0) 
    print('mun=', MCT.mun/(Unit.cm*Unit.cm/Unit.V/Unit.s), 'cm**2/V/s')
    print('me0=', MCT.me0/Unit.me) 
    print('Mbb(10u,300K)=', Mblackbody() / (Unit.W/(Unit.m)**3),'W/m**3' )
    print('Mbb(10u,300K)Unit_in=', Mblackbody() )
    print('BackGroundRadiation =', BackGroundRadiation(MCT)/ (Unit.kg/(Unit.s)**3), ' kg/s**3')
    print('直接复合Br=', MCT.Br*Unit.s,'s**-1')
    print('taun0=', MCT.taun0/Unit.s)
    print('taup0=', MCT.taup0/Unit.s)
    print('tauA1i=', MCT.tauA1i/Unit.s)
    print('tauA7i=', MCT.tauA7i/Unit.s)    